﻿#include "SSqlconnectionPool.h"

SSqlconnectionPool::SSqlconnectionPool(QWidget* parent)
	:m_port(3306)
	,m_databseType("QMYSQL")
	,m_maxconnectioncount(10)
	,m_waitInterval(100)
	,m_waitTime(1000)
	,QWidget(parent)
{

}

SSqlconnectionPool* SSqlconnectionPool::instance()
{
	static SSqlconnectionPool* ins = nullptr;
	if (!ins)
	{
		ins = new SSqlconnectionPool;
	}
	return ins;
}

SSqlconnectionPool::~SSqlconnectionPool()
{
	QMutexLocker locker(&m_openMutex);

	for (const auto& con_name : m_useConnections)
	{
		QSqlDatabase::removeDatabase(con_name);
	}

	for (const auto& con_name : m_unuseConnections)
	{
		QSqlDatabase::removeDatabase(con_name);
	}
}

QSqlDatabase SSqlconnectionPool::openConnection()
{
	//Debug() << __FUNCTION__;


	QMutexLocker<QMutex> locker(&m_openMutex);


	//当前总连接数：
	int count = m_useConnections.count() + m_unuseConnections.count();

	//如果所有连接都在使用中count == m_maxconnectioncount;并且没有未使用的连接
	//如果没有未使用的连接；并且总连接数等于最大连接数；并且没有到达等待时间；则等待其他线程关闭连接
	for (size_t i = 0; i < m_waitTime && m_unuseConnections.isEmpty() && count == m_maxconnectioncount; i += m_waitInterval)
	{
		//等待其他的连接被关闭：
		m_waitCond.wait(&m_openMutex, m_waitInterval);

		//重新计算一下总连接数：
		count = m_useConnections.count() + m_unuseConnections.count();
	}


	QString con_name;
	//判断是否创建新的连接：
	if (m_unuseConnections.count() > 0)
	{
		con_name = m_unuseConnections.dequeue();
	}
	else if (count < m_maxconnectioncount)
	{
		con_name = QString("connection-%1").arg(count + 1);
	}
	else
	{
		qWarning() << "all connections is used";


		//发送给服务器界面显示的信号：
		//emit SqlData("all connections is used");


		return QSqlDatabase();
	}


	//创建新的连接，并判断是否打开，并加入已经被使用的连接量中：
	auto db = createConnection(con_name);
	if (db.isOpen())
	{
		m_useConnections.enqueue(con_name);
	}
	return db;
}

void SSqlconnectionPool::closeConnection(QSqlDatabase db)
{
	QMutexLocker locker(&m_openMutex);


	auto con_name = db.connectionName();
	if (m_useConnections.contains(con_name))
	{
		m_useConnections.removeOne(con_name);
		m_unuseConnections.enqueue(con_name);

		//唤醒一个正在打开的线程：
		m_waitCond.wakeOne();
	}


	qDebug() << "useConnections is >" << m_useConnections.count();
	qDebug() << "unuseConnections is >" << m_unuseConnections.count();
	qDebug() << "totalConnections is >" << m_useConnections.count() + m_unuseConnections.count();


	//发送给服务器界面显示的信号：
	
	emit SqlData(QString("use>%1unuse>%2total>%3")
		.arg(useConnections())
		.arg(unuseConnections())
		.arg(useConnections() + unuseConnections()));
		
}

QSqlDatabase SSqlconnectionPool::createConnection(const QString& con_name)
{
	//如果该连接已经存在：
	if (QSqlDatabase::contains(con_name))
	{
		auto db = QSqlDatabase::database(con_name);
		if (db.isOpen())
		{
			return db;
		}
	}


	//不存在就创建：
	QSqlDatabase db = QSqlDatabase::addDatabase(m_databseType, con_name);
	db.setPort(m_port);
	db.setHostName(m_hostname);
	db.setDatabaseName(m_databasename);
	db.setUserName(m_username);
	db.setPassword(m_password);


	if (!db.open())
	{
		qWarning() << "create connection failed " << db.lastError().text();


		//发送给服务器界面显示的信号：
		//emit SqlData(QString("create connection failed ,errorText:%1").arg(db.lastError().text()));


		return QSqlDatabase();
	}
	
	return db;
}

void SSqlconnectionPool::releaseConnection(QSqlDatabase db)
{
	auto con_name = db.connectionName();
	QSqlDatabase::removeDatabase(con_name);
}




SConnectionWarp::SConnectionWarp()
{
	
}

SConnectionWarp::~SConnectionWarp()
{
	auto pool = SSqlconnectionPool::instance();
	pool->closeConnection(m_db);
}

QSqlDatabase SConnectionWarp::openConnection()
{
	m_db = SSqlconnectionPool::instance()->openConnection();
	return m_db;
}
